﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.Xml.Schema;
using System.Windows;

namespace BetaSeriesConnector
{
    [XmlType(AnonymousType = true)]
    [XmlRoot(ElementName = "root", Namespace = "", IsNullable = false)]
    [Serializable]
    public class BSResponse
    {
        [XmlElement("key", Form = XmlSchemaForm.Unqualified)]
        public string APIKey { get; set; }

        [XmlArray("shows", Form = XmlSchemaForm.Unqualified)]
        [XmlArrayItem("show")]
        public BSShow[] Shows { get; set; }

        [XmlArray("errors", Form = XmlSchemaForm.Unqualified)]
        [XmlArrayItem("error")]
        public BSError[] Errors { get; set; }

        [XmlArray("subtitles", Form = XmlSchemaForm.Unqualified)]
        [XmlArrayItem("subtitle")]
        public BSSubtitlesCollection[] Subtitles { get; set; }

        [XmlArray("seasons", Form = XmlSchemaForm.Unqualified)]
        [XmlArrayItem("season")]
        public BSSeason[] Seasons { get; set; }

        public void LogErrors(object sender, string context)
        {
            foreach (var error in this.Errors)
                error.Log(sender, context);
        }
    }

    [XmlType(AnonymousType = true)]
    [Serializable]
    public class BSError
    {
        [XmlElement("code", Form = XmlSchemaForm.Unqualified)]
        public int Code { get; set; }

        [XmlElement("content", Form = XmlSchemaForm.Unqualified)]
        public string Content { get; set; }

        public void Log(object sender, string context)
        {
            TV_Organizer.LogsManager.Log(sender, string.Format("{0} --> {1} ({2})", context, this.Content, this.Code));
        }
    }

    [XmlType(AnonymousType = true)]
    [Serializable]
    public class BSShow : TV_Organizer.TVDB.TVDBShow
    {
        [XmlElement("url", Form = XmlSchemaForm.Unqualified)]
        public string Url { get; set; }

        [XmlElement("title", Form = XmlSchemaForm.Unqualified)]
        public string Title { get; set; }

        [XmlElement("id_thetvdb", Form = XmlSchemaForm.Unqualified)]
        public int Serialization_TVDBID { get; set; }

        public override string Name
        {
            get { return this.Title; }
        }

        public override string Source
        {
            get { return "BetaSeries"; }
        }

        public override int TVDBID
        {
            get { return this.Serialization_TVDBID; }
        }
    }

    [XmlType(AnonymousType = true)]
    [Serializable]
    public class BSSubtitlesCollection
    {
        [XmlElement("language", Form = XmlSchemaForm.Unqualified)]
        public string Language { get; set; }

        [XmlElement("source", Form = XmlSchemaForm.Unqualified)]
        public string Source { get; set; }

        [XmlElement("url", Form = XmlSchemaForm.Unqualified)]
        public string Url { get; set; }

        [XmlArray("content", Form = XmlSchemaForm.Unqualified)]
        [XmlArrayItem("item")]
        public string[] Content { get; set; }

        public IEnumerable<BSSubtitle> ToSubtitles()
        {
            var result = new List<BSSubtitle>();
            if (this.Content == null) return result;

            Application.Current.Dispatcher.Invoke(new System.Action<ICollection<BSSubtitle>>((r) =>
            {
                foreach (var content in this.Content)
                {
                    if (content == null) continue;
                    r.Add(new BSSubtitle()
                    {
                        Filename = content,
                        Url = this.Url,
                        Language = this.GetLanguage(this.Language, content),
                        Source = this.Source,
                    });
                }
            }), new object[] { result });

            return result;
        }

        private TV_Organizer.Language GetLanguage(string bsLanguage, string filename)
        {
            switch (bsLanguage)
            {
                case "VO":
                    return TV_Organizer.Language.English;
                case "VF":
                    return TV_Organizer.Language.French;
                case "VOVF":
                    var file = filename.ToLowerInvariant();

                    if(file.Contains(".vo."))
                        return TV_Organizer.Language.English;
                    else if(file.Contains(".vf."))
                        return TV_Organizer.Language.French;
                    
                    var language = TV_Organizer.Language.ValidLanguages.FirstOrDefault(l => file.Contains("."+l.LongName+"."));
                    if(language != null) return language;

                    language = TV_Organizer.Language.ValidLanguages.FirstOrDefault(l => file.Contains("."+l.ShortName+"."));
                    if(language != null) return language;

                    return TV_Organizer.Language.Unknown;
                default:
                    return TV_Organizer.Language.Unknown;
            }
        }
    }

    [XmlType(AnonymousType = true)]
    [Serializable]
    public class BSSeason
    {
        [XmlElement("number", Form = XmlSchemaForm.Unqualified)]
        public int SeasonNumber { get; set; }

        [XmlArray("episodes", Form = XmlSchemaForm.Unqualified)]
        [XmlArrayItem("episode")]
        public BSEpisode[] Episodes { get; set; }

        public TV_Organizer.Episode GetEpisode(int episodeNumber)
        {
            var bsEpisode = this.Episodes.FirstOrDefault(e => e.EpidoseNumber == episodeNumber);
            if (bsEpisode == null) return null;

            return new TV_Organizer.Episode(this.SeasonNumber, bsEpisode.EpidoseNumber, bsEpisode.Title);
        }
    }

    [XmlType(AnonymousType = true)]
    [Serializable]
    public class BSEpisode
    {
        [XmlElement("episode", Form = XmlSchemaForm.Unqualified)]
        public int EpidoseNumber { get; set; }

        [XmlElement("number", Form = XmlSchemaForm.Unqualified)]
        public string SeasonEpisodeString { get; set; }

        [XmlElement("title", Form = XmlSchemaForm.Unqualified)]
        public string Title { get; set; }
    }

    public class BSSubtitle : TV_Organizer.Subtitles.Subtitle
    {
        public string Url { get; set; }
    }
}
